package com.zhaoyue.study.concurrency.pools;

import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 * User: Administrator
 * Date: 2017/3/8
 * Time: 16:37
 * To change this template use File | Settings | File Templates.
 */
public class Memoizer<A,V> implements Computable<A,V> {

    private final ConcurrentHashMap<A,Future<V>> cache = new ConcurrentHashMap<>();
    private final Computable<A,V> c;

    public Memoizer(Computable<A,V> c){
        this.c = c;
}

    @Override
    public V comput(final A arg) throws InterruptedException {
        while (true){
            Future<V> f = cache.get(arg);
            if(f == null){
                Callable<V> eval = new Callable<V>() {
                    @Override
                    public V call() throws Exception {
                        return c.comput(arg);
                    }
                };

                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg,ft);
                if(f == null){
                    f = ft;
                    ft.run();
                }
            }

            try{
                return f.get();
            }catch (CancellationException e){
                cache.remove(arg,f);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
